.set noreorder
.set noat
.globl __start

#define LOAD_WORD(dst, off) \
  sll $t7, off, 1; \
  addu $t7, $s0, $t7; \
  lw dst, 0($t7); \
  lw $t7, 4($t7); \
  sll $t7, $t7, 16; \
  or dst, dst, $t7

__start:
    nop
    
load_elf_header:
    la $s0, 0xBE000000 # FLASH starts on memory address 0xBE000000
    la $t1, 0
    LOAD_WORD($t0,$t1)
    la $t1, 0x464C457F
    beq $t0, $t1, magic_correct
    nop
    b error
    nop

magic_correct:
    la $t1, 0x18
    LOAD_WORD($s1,$t1) #e_entry
    la $t1, 0x1C
    LOAD_WORD($s2,$t1) #e_phoff
    la $t1, 0x2C
    LOAD_WORD($s3,$t1) #e_phnum
    
load_section_header:
    addiu $t1, $s2, 0x4 #p_offset
    LOAD_WORD($t4,$t1)
    addiu $t1, $s2, 0x8 #p_va
    LOAD_WORD($t5,$t1)
    addiu $t1, $s2, 0x10 #p_size
    LOAD_WORD($t6,$t1)
    beq $t5, $zero, next_section
    nop
    beq $t6, $zero, next_section
    nop
    la $t3, 0x0

load_inst:
    addu $t1, $t4, $t3
    LOAD_WORD($t0,$t1)
    addu $t1, $t5, $t3
    sw $t0, 0($t1)
    addiu $t3, 0x4
    subu $t2, $t6, $t3
    bgtz $t2, load_inst
    nop

next_section:
    addiu $s2, $s2, 0x20
    addiu $s3, $s3, 0xFFFF
    bgtz $s3, load_section_header
    nop

start_kernel:
    jr $s1
    nop
    b done
    nop

done:
    b done
    nop
    
error:
    b error
    nop

